inline
int NDK_OS::bind (NDK_HANDLE handle,
	struct sockaddr *addr,
	int addrlen)
{
#if defined NDK_WIN32
    return NDK_SOCKCALL_RETURN (::bind (handle,
		addr,
		addrlen),
	    int,
	    SOCKET_ERROR);
#elif defined NDK_LINUX
    return ::bind (handle,
	    addr,
	    static_cast<socklen_t>(addrlen));
#endif
}
inline
int NDK_OS::listen (NDK_HANDLE handle,
	int backlog)
{
#if defined NDK_WIN32
    return NDK_SOCKCALL_RETURN (::listen (handle,
		backlog),
	    int,
	    SOCKET_ERROR);
#elif defined NDK_LINUX
    return ::listen (handle,
	    backlog);
#endif
}
inline
NDK_HANDLE NDK_OS::accept (NDK_HANDLE listen_handle,
	struct sockaddr *addr,
	int *addrlen)
{
#if defined NDK_WIN32
    return NKD_SOCKCALL_RETURN (::accept (listen_handle,
		addr,
		addrlen),
	    NDK_HANDLE, 
	    NDK_INVALID_HANDLE);
#elif defined NDK_LINUX
    return ::accept (listen_handle, 
	    addr, 
	    reinterpret_cast<socklen_t*>(addrlen));
#endif
}
inline
int NDK_OS::connect (NDK_HANDLE handle,
	const struct sockaddr *addr,
	int addrlen)
{
#if defined NDK_WIN32
    return NKD_SOCKCALL_RETURN (::connect (handle,
		addr,
		addrlen),
	    int,
	    SOCKET_ERROR);
#elif defined NDK_LINUX
    return ::connect (handle,
	    addr,
	    static_cast<socklen_t>(addrlen));
#endif
}
inline
NDK_HANDLE NDK_OS::socket (int domain, int type, int protocol)
{
    return ::socket (domain, type, protocol);
}
inline
int NDK_OS::closesocket (NDK_HANDLE handle)
{
#if defined NDK_WIN32
    return ::closesocket (handle);
#elif defined NDK_LINUX
    return ::close (handle);
#endif
}
inline
int NDK_OS::setsock_reuseaddr (NDK_HANDLE handle, int val)
{
    return ::setsockopt (handle, 
	    SOL_SOCKET, 
	    SO_REUSEADDR, 
	    (const void*)&val,
	    sizeof (val));
}
inline
int NDK_OS::setsock_rcvbuf (NDK_HANDLE handle, size_t size)
{
    if (size == 0) return -1;
    return ::setsockopt (handle, 
	    SOL_SOCKET, 
	    SO_RCVBUF, 
	    (const void*)&size, 
	    sizeof (size));
}
inline
int NDK_OS::setsock_sndbuf (NDK_HANDLE handle, size_t size)
{
    if (size == 0) return -1;
    return ::setsockopt (handle, 
	    SOL_SOCKET, 
	    SO_SNDBUF, 
	    (const void*)&size, 
	    sizeof (size));
}
inline
int NDK_OS::getsock_error (NDK_HANDLE handle, int &err)
{
#if defined NDK_WIN32
    int len = sizeof (int);
    return NDK_SOCKCALL_RETURN (::getsockopt (handle,
	    SOL_SOCKET,
	    SO_ERROR,
	    &err,
	    &len),
	    int,
	    SOCKET_ERROR);
#elif defined NDK_LINUX
    socklen_t len = sizeof (int);
    return ::getsockopt (handle,
	    SOL_SOCKET,
	    SO_ERROR,
	    &err,
	    &len);
#endif
}
inline
int NDK_OS::recv (NDK_HANDLE handle,
	void *buff,
	size_t len,
	int flags)
{
#if defined NDK_WIN32
    return NDK_SOCKCALL_RETURN (::recv (handle, buff, len, flags),
	    int,
	    SOCKET_ERROR);
#elif defined NDK_LINUX
    return ::recv (handle, buff, len, flags);
#endif
}
inline
int NDK_OS::recvfrom (NDK_HANDLE handle,
	void *buff,
	size_t len,
	int flags,
    struct sockaddr *from, 
    int *fromlen)
{
#if defined NDK_WIN32
    return NDK_SOCKCALL_RETURN (::recv (handle, buff, 
                static_cast<int>(len), flags,
                from, fromlen),
            int,
            SOCKET_ERROR);
#elif defined NDK_LINUX
    return ::recvfrom (handle, buff, len, flags, from, (socklen_t *)fromlen);
#endif
}
inline
int NDK_OS::send (NDK_HANDLE handle, 
	    const void *buff, 
	    size_t len, 
	    int flags) 
{
#if defined NDK_WIN32
    return NDK_SOCKCALL_RETURN (::send (handle, buff, len, flags),
	    int,
	    SOCKET_ERROR);
#elif defined NDK_LINUX
    return ::send (handle, buff, len, flags);
#endif
}
inline
int NDK_OS::sendto (NDK_HANDLE handle, 
	    const void *buff, 
	    size_t len, 
	    int flags, 
        const struct sockaddr *to, 
        int tolen)
{
#if defined NDK_WIN32
    return NDK_SOCKCALL_RETURN (::sendto (handle, buff, 
                static_cast<int>(len), flags, to, tolen),
	    int,
	    SOCKET_ERROR);
#elif defined NDK_LINUX
    return ::sendto (handle, buff, len, flags, to, tolen);
#endif
}
inline
int NDK_OS::open (const char *filename,
	int mode,
	mode_t perms)
{
#if defined NDK_WIN32
    DWORD access = GENERIC_READ;
    if (NDK_BIT_ENABLED (mode, O_WRONLY))
	access = GENERIC_WRITE;
    else if (NDK_BIT_ENABLED (mode, O_RDWR))
	access = GENERIC_READ | GENERIC_WRITE;
    DWORD creation = OPEN_EXISTING;
    if ((mode & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
	creation = CREATE_NEW;
    else if ((mode & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
	creation = CREATE_ALWAYS;
    else if (NDK_BIT_ENABLED (mode, O_CREAT))
	creation = OPEN_ALWAYS;
    else if (NDK_BIT_ENABLED (mode, _O_TRUNC))
	creation = TRUNCATE_EXISTING;

    DWORD flags = FILE_FLAG_SEQUENTIAL_SCAN;
    DWORD shared_mode = perms;
    SECURITY_ATTRIBUTES sa;
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = TRUE;
    NDK_HANDLE h = ::CreateFile (filename,
	    access,
	    shared_mode,
	    &sa,
	    creation,
	    flags,
	    0);
    if (NDK_BIT_ENABLED (mode, O_APPEND))
    {
	LONG high_size = 0;
	if (h != NDK_INVALID_HANDLE
		&& ::SetFilePointer (h,
		    0,
		    &high_size,
		    FILE_END) == INVALID_SET_FILE_POINTER
		&& GetLastError () != NO_ERROR)
	{
	    return NDK_INVALID_HANDLE;
	}
    }
    return h;
#elif defined NDK_LINUX
    return ::open (filename, mode, perms);
#endif
}
inline
int NDK_OS::open (const char *filename,
	int flags)
{
#if defined NDK_WIN32
    ;
#elif defined NDK_LINUX
    return NDK_OS::open (filename, flags, 0);
#endif
}
inline
int NDK_OS::read (NDK_HANDLE handle,
	void *buff,
	size_t len)
{
#if defined NDK_WIN32
    return -1;
#elif defined NDK_LINUX
    return ::read (handle, buff, len);
#endif
}
inline
int NDK_OS::write (NDK_HANDLE handle,
	const void *buff,
	size_t len)
{
#if defined NDK_WIN32
    return -1;
#elif defined NDK_LINUX
    return ::write (handle, buff, len);
#endif
}
inline
int NDK_OS::readv (NDK_HANDLE handle,
	iovec iov[],
	size_t count)
{
#if defined NDK_WIN32
    DWORD flags = 0;
    DWORD bytes_received = 0;
    int result = ::WSARecv ((SOCKET) handle,
	     (WSABUF *) iov,
	     count,
	     &bytes_received,
	     &flags,
	     0,
	     0);
    if (result == SOCKET_ERROR)
	return -1;
    return (int)bytes_received;
#elif defined NDK_LINUX
    return ::readv (handle, iov, count);
#endif
}
inline
int NDK_OS::writev (NDK_HANDLE handle,
	const iovec iov[],
	size_t count)
{
#if defined NDK_WIN32
    DWORD bytes_sent = 0;
    int result = ::WSASend ((SOCKET) handle,
	    (WSABUF *) iov,
	    count,
	    &bytes_sent,
	    0,
	    0,
	    0);
    if (result == SOCKET_ERROR)
	return -1;
    return (int)bytes_sent;
#elif defined NDK_LINUX
    return ::writev (handle, iov, count);
#endif
}
inline
int NDK_OS::close (NDK_HANDLE handle)
{
    return ::close (handle);
}
inline
int NDK_OS::stat (const char *name,
	struct stat *st_buf)
{
#if defined NDK_WIN32
    return ::_stat (name, st_buf);
#elif defined NDK_LINUX
    return ::stat (name, st_buf);
#endif
}
inline
int NDK_OS::mkdir (const char *name,
	mode_t type)
{
#if defined NDK_WIN32
    unused_arg (type);
    ::_mkdir (name);
#elif defined NDK_LINUX
    return ::mkdir (name, type);
#endif
}
inline
int NDK_OS::rename (const char *old_name,
	const char *new_name)
{
#if defined NDK_WIN32
    int flags = MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING;
    if (::MoveFileEx (old_name, new_name, flags) == 0)
	return -1;
#elif defined NDK_LINUX
    return ::rename (old_name, new_name);
#endif
}


